/*
 * =====================================================================================
 *       Filename:  xsync.c
 *    Description:  文件同步传输服务主程序
 *        Version:  1.0
 *        Created:  2015-01-07 15:40
 *         Author:  mien, m@p58.net
 * =====================================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
#include <signal.h>

#include "net.h"
#include "http/http.h"
#include "pool.h"
#include "config.h"

#define DEFAULT_CONFIG_FILE "conf/xsync.conf"

static void daemonize() {
    int fd;

    if (fork() != 0) exit(0);
    setsid();

    if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
        dup2(fd, STDIN_FILENO);
        dup2(fd, STDOUT_FILENO);
        dup2(fd, STDERR_FILENO);
        if (fd > STDERR_FILENO) close(fd);
    }
}

static void sigShutdownHandler(int sig) {
    char *msg;

    switch (sig) {
    case SIGINT:
        msg = "Received SIGINT scheduling shutdown...";
        break;
    case SIGTERM:
        msg = "Received SIGTERM scheduling shutdown...";
        break;
    default:
        msg = "Received shutdown signal, scheduling shutdown...";
    }
    printf(msg);

    freeConfig();
    poolDestroy();
    cmdFree();

    exit(1);
}

static char* AbsConfigPath(const char* app, const char* filename) {
    static char path[4096];
    if (filename[0] == '/') {
        strcpy(path, filename);
    }
    else {
        realpath(app, path);
        char* dst = strrchr(path, '/');
        dst = (dst == NULL) ? path : dst + 1;
        strcpy(dst, filename);
    }
    return path;
}

void setupSignalHandlers(void) {
    struct sigaction act;

    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    act.sa_handler = sigShutdownHandler;
    sigaction(SIGTERM, &act, NULL);
    sigaction(SIGINT, &act, NULL);
}

int main(int argc, char* argv[])
{
    char* conf = AbsConfigPath(argv[0], (argc == 2) ? argv[1] : DEFAULT_CONFIG_FILE);
    loadConfig(conf);

    setUidGid();

    signal(SIGHUP, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    setupSignalHandlers();

    if (!strcmp(getServerConfig("daemonize"), "yes"))
        daemonize();

    poolInit();
    cmdInit();

    tcpListen(
        getServerConfig("host"),
        getServerConfig("port"),
        poolHandle);
    
    return EXIT_SUCCESS;
}
